﻿//----------------------------------------------------------------------
// <copyright file="SyncOperator.cs" company="NTT DATA BEEN (China)">
// Copyright (c)2012 NTT DATA BEEN (China) Information Technology Co.,Ltd.
// </copyright>
// <author> lidawei </author>
// <summary>
// システム名称　　：
// モジュールＩＤ　：
// モジュール名称　：
// 機能概要　　　　：SyncOperator类 
// 改訂履歴　　　　：
// 2012-08-01 新規 lidawei    Been0001   
// </summary>
//---------------------------------------------------------------------- 

namespace Ntt.NttData.Been.Management.SolutionA.Sync.Operator.BLL
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using Common.Data;
    using Common.Log;
    using Model;

    public  class SyncOperator
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="SyncOperator"/> class.
        /// </summary>
        /// <param name="showmsg">if set to <c>true</c> [showmsg].</param>
        public SyncOperator(bool showmsg)
        {
            _showMsg = showmsg;
        }

        /// <summary>
        /// Dones this instance.
        /// </summary>
        public void Done()
        {
            LogHelper.WriteLog(LogType.StartProc, "D0010");

            InitData();
            SetCase();

            LogHelper.WriteLog(LogType.EndProc, "D0011");

        }

        /// <summary>
        /// Inits the data.
        /// </summary>
        private void InitData()
        {
            LogHelper.WriteLog(LogType.StartProc, "D0015");

            DisplayMsg("同步数据前数据准备", "PermissionCaseMaServer");
            CachePermisssionCaseMaServer.GetInstance().InitData();
            DisplayMsg("同步数据前数据准备", "BaseMaServerInfo");
            CacheBaseMaServerInfo.GetInstance().InitData();
            DisplayMsg("同步数据前数据准备", "OperatorJobRank");
            CacheSourceJobRank.GetInstance().InitData();

            LogHelper.WriteLog(LogType.EndProc, "D0016");

        }

        /// <summary>
        /// true show msg
        /// </summary>
        private readonly bool _showMsg;

        /// <summary>
        /// Displays the Message.
        /// </summary>
        /// <param name="tittle">The tittle.</param>
        /// <param name="message">The message.</param>
        private void DisplayMsg(string tittle, string message)
        {
            if (_showMsg)
            {
                ShowMessage.DisplayMsg(tittle,message);
                ShowMessage.Show(tittle,message);
            }
        }

        /// <summary>
        /// Sets the case.
        /// </summary>
        private void SetCase() 
        {
            LogHelper.WriteLog(LogType.StartProc, "D0020");

             //1.先得到MasterDB里PermisssionCaseMaServer表中的maserverid 和 case的对照关系
            var permisssionCaseMaServerList = CachePermisssionCaseMaServer.GetInstance().PermisssionCaseMaServerList;

            //2.循环BaseMaServerInfo的记录，找到每条MA的DatabaseConnection
            var baseMaServerInfoList =  CacheBaseMaServerInfo.GetInstance().BaseMaServerInfoList;
  
            DisplayMsg("同步数据", "开始");

            LogHelper.WriteLog(LogType.Operation, "D0021");

            //补充Ma对应的caseId
            if (permisssionCaseMaServerList != null)
            {
                baseMaServerInfoList.ForEach(t =>{ 
                    
                    List<string> caseIds =permisssionCaseMaServerList
                                                         .Where(c => c.MaServerId == t.ServerId)
                                                         .Select(c => c.CaseId).ToList();
                    
                    var sourceRanks = GetOperatorRank(caseIds);
                    
                    new System.Threading.Thread(() => SyncOpRank(t.DbConnString,sourceRanks)).Start();

                });
            } 
        }

        /// <summary>
        /// Syncs the op rank.
        /// </summary>
        /// <param name="dbconn">The dbconn.</param>
        /// <param name="sourceRanks">The source ranks.</param>
        private void  SyncOpRank(string dbconn, IEnumerable<EntityOperator> sourceRanks)
        { 
            int effactRowsAdd = 0, effactRowsUpdate = 0, effactRowsDel = 0;
            try
            {
                IEnumerable<EntityOperator> currentOpRanks = TargetDAL.Ma19Database.GetOperatorsRank(dbconn);

                //数据比较前数据排序

                if (sourceRanks != null)
                {
                    List<EntityOperator> sourceT = sourceRanks.OrderBy(t => t.OperatorNo).ToList();
                    List<EntityOperator> currentT = null;

                    if (currentOpRanks != null)
                    {
                          currentT = currentOpRanks.OrderBy(t => t.OperatorNo).ToList();
                    }

                    int i = 0, j = 0;
                    ISyncAction syncAction = new SyncAction();

                    while (i <  sourceT.Count )
                    {
                        EntityOperator sourceItem = sourceT[i];
                        EntityOperator currentItem = null;

                        if (currentT != null && j < currentT.Count)
                            currentItem = currentT[j];

                        ESyncAction action = sourceItem.GetSyncAction(currentItem);

                    
                        switch (action)
                        {
                            case ESyncAction.Insert:
                                //inset();
                                effactRowsAdd += syncAction.Insert(dbconn, sourceItem);
                                i++;
                                break;
                            case ESyncAction.Update:
                                //update();
                                effactRowsUpdate += syncAction.Update(dbconn, sourceItem);
                                i++;
                                j++;
                                break;
                            case ESyncAction.Delete:
                                //delete();
                                if (currentItem != null)
                                    effactRowsDel += syncAction.Delete(dbconn, currentItem.OperatorNo);
                                j++;
                                break;
                            case ESyncAction.Ignore:
                                i++;
                                j++;
                                break;
                        }

                        DisplayMsg(  sourceItem.OperatorNo , action.ToString());
                        ShowMessage.Show("同步数据动作", action.ToString());
                        ShowMessage.ShowProperty(sourceItem);
 
                    }

                    //delete 
                    if (currentT != null && (i == sourceT.Count && j < currentT.Count))
                    {
                        while (j < currentT.Count)
                        {
                            EntityOperator currentItem = currentT[j];
                            if (currentItem != null)
                                effactRowsDel += syncAction.Delete(dbconn, currentItem.OperatorNo);
                            j++;

                            if (currentItem != null) 
                                DisplayMsg( currentItem.OperatorNo , ESyncAction.Delete.ToString());
                            ShowMessage.Show("同步数据动作", ESyncAction.Delete.ToString());
                            ShowMessage.ShowProperty(currentItem);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                DisplayMsg("同步数据动作Error", ex.ToString());
                ShowMessage.Show("同步数据动作Error");
                ShowMessage.ShowProperty(ex);
            }
            finally
            {
                LogHelper.WriteLog(LogType.Operation, "DXXXX", string.Format("Insert row count:{0}", effactRowsAdd));
                LogHelper.WriteLog(LogType.Operation, "DXXXX", string.Format("Update row count:{0}", effactRowsUpdate));
                LogHelper.WriteLog(LogType.Operation, "DXXXX", string.Format("delete row count:{0}", effactRowsDel));

                DisplayMsg("同步数据", "结束");
            } 

        }

        /// <summary>
        /// Gets the operator rank.
        /// 得到Ma3.0里 的权限
        /// 
        /// </summary>
        /// <param name="caseIds">The case ids.</param>
        /// <returns></returns>
        private IEnumerable<EntityOperator> GetOperatorRank(List<string> caseIds)
        {
            DisplayMsg("同步数据", "得到3.0里最原始的权限");
            //得到3.0里最原始的权限
           // var sourceRank = SourceDAL.ManagementToolsDatabase.GetOperatorsRanks(caseIds.ToArray());
            var sourceRank = CacheSourceJobRank.GetInstance().EntitySourceOperatorList.FindAll(t =>  caseIds.Contains(t.CaseId) );

            //把多案件的权限 整合在一起
            //case A: A,B,C
            //case B: D,E
            //result rank -> A,B,C,D,E 
            var operatorDistinctRank =
                sourceRank.GroupBy(t => new {t.OperatorId})
                    .Select(group => new EntitySourceOperator
                                         {
                                             OperatorId = @group.Key.OperatorId,
                                             OperatorName = @group.First().OperatorName,
                                             OperatorNamekana = @group.First().OperatorNamekana,
                                             OperatorPass = @group.First().OperatorPass,
                                             Rank = JoinRank(  @group.Select(item=>item.Rank ).ToList()),
                                             //更新时间取最大值
                                             UpadteTime = @group.Max(t=>t.UpadteTime),
                                         }).ToList();
           List<EntityOperator> targetOperatorRank = operatorDistinctRank.ConvertAll(t=>t.Convert());
             
            //去掉转换失败的
           targetOperatorRank.RemoveAll(t => t.OperatorGender == -1);

           return targetOperatorRank;
        }

        /// <summary>
        /// Joins the rank.
        /// </summary>
        /// <param name="ranks">The ranks.</param>
        /// <returns></returns>
        private JobRank JoinRank(List<JobRank> ranks)
        {
            JobRank rank = JobRank.None;

            ranks.ForEach(t => rank = rank | t);

            return rank;
        }
    }
}
